#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file: image.py
@time: 2024-06-25 11:31
@desc: 
"""
import traceback
from urllib.parse import urlencode
from flask import Blueprint, request, jsonify

from common_tools import apply_formatting
from global_scope import get_db, images_sheet_name
from project_model import Image
from tools import log_operations, token_required
from tools import get_images_df, excel_to_images, delete_image_from_image_bed
from io import BytesIO
from flask import send_file
import pandas as pd

db = get_db()
image_bp = Blueprint('image', __name__, url_prefix='/images')


@image_bp.route('', methods=['POST'])
@log_operations
@token_required
def add_image():
    data = request.json
    imageUrl = data.get('imageUrl')

    if not imageUrl:
        return jsonify({"code": 1, "message": "imageUrl is required"}), 400

    image = Image.query.filter_by(imageUrl=imageUrl).first()
    if not image:
        image = Image(image_url=imageUrl)
        remark = data.get('remark')
        if remark:
            image.remark = remark

        db.session.add(image)
        db.session.commit()

    return jsonify({"code": 0, "message": "Image added successfully", "data": image.id}), 201


@image_bp.route('/<int:image_id>', methods=['PATCH'])
@log_operations
@token_required
def update_image(image_id):
    data = request.json
    image = Image.query.get(image_id)
    if not image:
        return jsonify({"code": 1, "message": "Image not found"}), 404

    if 'imageUrl' in data and image.imageUrl != data["imageUrl"]:
        # 删除图床中的图片，并更新数据库
        if delete_image_from_image_bed(image, request):
            # 添加新的图片
            image.imageUrl = data['imageUrl']
        else:
            return jsonify(
                {"code": 1, "message": "Failed to delete image from external service"}), 500
    if 'remark' in data:
        image.remark = data['remark']

    db.session.commit()

    return jsonify({"code": 0, "message": "Image updated successfully"}), 200


@image_bp.route('/<int:image_id>', methods=['DELETE'])
@log_operations
@token_required
def delete_image(image_id):
    image = Image.query.get(image_id)
    if not image:
        return jsonify({"code": 1, "message": "Image not found"}), 404

    if not delete_image_from_image_bed(image, request):
        request.logger.error(f"Image {image.imageUrl} deleted failed")
    # 从数据库中删除记录
    db.session.delete(image)
    db.session.commit()
    return jsonify({"code": 0, "message": "Image deleted successfully"}), 200


@image_bp.route('', methods=['GET'])
@log_operations
@token_required
def get_images():
    """
     请将查询接口，添加分页查询代码逻辑，客户端的分页请求参数为
     pageNo integer
     pageSize integer
    响应体样式，参考：
    {
        "code": 0,
        "message": "OK",
        "data": {
            "pageData": data,
            "total": len(data),
        },
        "originUrl": "请求的url"
    }
    其中 originUrl 需要带原始的query参数，而不仅仅是接口路由地址
    """
    page_no = request.args.get('pageNo', default=1, type=int)
    page_size = request.args.get('pageSize', default=10, type=int)  # 假设默认每页10条数据

    query = Image.query
    # 根据remark字段进行模糊查询
    remark = request.args.get('remark', default=None, type=str)
    if remark:
        query = Image.query.filter(Image.remark.contains(remark))
    # 根据imgUrl字段进行准确查询
    imgUrl = request.args.get('imageUrl', default=None, type=str)
    if imgUrl:
        query = Image.query.filter(Image.imageUrl == imgUrl)

    # Image模型有一个id字段作为主键，可以根据该字段进行排序和分页
    images = query.order_by(Image.id).paginate(page=page_no, per_page=page_size, error_out=False)

    items = images.items  # 获取当前页的数据列表
    total = images.total  # 获取总数据量

    # 构造响应数据
    data = [{
        "id": img.id, "imageUrl": img.imageUrl,
        "remark": img.remark, "createTime": img.createTime,
        "updateTime": img.updateTime
    } for img in items]  # 提取需要的数据字段
    origin_url = request.base_url + '?' + urlencode(request.args)  # 构造带有原始查询参数的完整URL

    return jsonify({
        "code": 0,
        "message": "OK",
        "data": {
            "pageData": data,
            "total": total,  # 注意这里是总数据量，而不是当前页的数据量
        },
        "originUrl": origin_url
    }), 200


@image_bp.route('/upload', methods=['POST'])
@log_operations
@token_required
def upload_images():
    if 'file' not in request.files:
        return jsonify({"code": 1, "message": "No file part"}), 400

    file = request.files['file']
    if file.filename == '':
        return jsonify({"code": 1, "message": "No selected file"}), 400

    try:
        new_objs, updated_objs = excel_to_images(file, request)
        return jsonify({
            "code": 0,
            "message": f"Contacts uploaded successfully: {new_objs} added, {updated_objs} updated"
        }), 201
    except Exception as e:
        tb = traceback.format_exc()
        request.trace_logger.error(f"Exception occurred: {str(e)}\n{tb}")
        return jsonify({"code": 1, "message": str(e)}), 500


@image_bp.route('/download', methods=['GET'])
@log_operations
@token_required
def download_images():
    output = BytesIO()
    with pd.ExcelWriter(output, engine='openpyxl') as writer:
        df_objs = [
            (get_images_df(), images_sheet_name),
        ]
        # 写入数据
        for df, sheet_name in df_objs:
            df.to_excel(writer, index=False, sheet_name=sheet_name)
            apply_formatting(writer.sheets[sheet_name], df)
    output.seek(0)

    return send_file(output, download_name="Images.xlsx", as_attachment=True)
